package com.hulk.ratel.common.util;

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import lombok.extern.slf4j.Slf4j;

/**
 * JAXB工具，通过使用注解，实现java对象与XML文件的相互转换
 * @author 
 */
@Slf4j
public class JaxbUtil {
	private static final ConcurrentHashMap<Class<?>, JAXBContext> jaxbContextMap = new ConcurrentHashMap<Class<?>,JAXBContext>();
	
	/**
     * 将JAXB实现对象转换成XML格式的字符串
     * @param <T> 这里的类是具体类，不能是接口
     * @param tclz 转换对象实例
     * @return
     */
    public static <T> String marshToXmlBinding(Class<T> tclz,T t)  {
            JAXBContext jc = null;
            StringWriter sw = new  StringWriter ();
			try {
				if(jaxbContextMap.get(tclz)==null) {
				    Map<String, String> properties = new HashMap<String, String>();
					jc = JAXBContext.newInstance(new Class<?>[]{tclz},properties);
					jaxbContextMap.put(tclz, jc);
				}else{
					jc = jaxbContextMap.get(tclz);
				}
				
				Marshaller u = jc.createMarshaller();
				// XML内容格式化
				u.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
				u.marshal(t, sw);
			} catch ( JAXBException e) {
				  e.printStackTrace();;
				  log.error("",e);
				 // throw new RuntimeException(e);
				  return null;
			}
            return sw.toString();
    }

    /**
     * 将JAXB实现对象转换成XML格式的字符串
     * @param <T> 这里的类是具体类，不能是接口
     * @param clzs 转换对象实例
     * @return
     */
    public static <T> String marshToXmlBinding(Class<T> [] clzs,T t)  {
        JAXBContext jc = null;
        StringWriter sw = new  StringWriter ();
        try {
            Map<String, String> properties = new HashMap<String, String>();
            jc = JAXBContext.newInstance(clzs,properties);
            Marshaller u = jc.createMarshaller();
            // XML内容格式化
            u.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
            u.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            u.marshal(t, sw);
        } catch ( JAXBException e) {
            e.printStackTrace();
            log.error("",e);
            // throw new RuntimeException(e);
            return null;
        }
        return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + sw.toString();
    }


    
    /**
     * 将XML格式的字符串转换成JAXB实现对象
     * @param <T> 这里的类是具体类，不能是接口
     * @param tclz
     * @param file 当目录存在文件不存在时，自动创建；当目录不存在时，将抛异常
     * @return
     */
    public static <T> void marshToXmlBinding(Class<T> tclz, T t, File file) {
        if (tclz == null || file == null) {
            return ;
        }
        
        try {
			JAXBContext jc = null;
			if (jaxbContextMap.get(tclz) == null) {
			    Map<String, String> properties = new HashMap<String, String>();
			    jc = JAXBContext.newInstance(new Class<?>[] {tclz}, properties);
			    jaxbContextMap.put(tclz, jc);
			} else {
			    jc = jaxbContextMap.get(tclz);
			}

			Marshaller u = jc.createMarshaller();
			u.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
			u.marshal(t, file);
		} catch ( JAXBException e) {
			  e.printStackTrace();;
			  log.error("",e);
			 // throw new RuntimeException(e);
		}
    }
    


    /**
     * 将XML格式的字符串转换成JAXB实现对象
     * @param <T> 这里的类是具体类，不能是接口
     * @param tclz
     * @param xmlstr
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T unmarshToObjBinding(Class<T> tclz,String xmlstr) {
        try {
            JAXBContext jc = null;
            if(jaxbContextMap.get(tclz)==null) {
                Map<String, String> properties = new HashMap<String, String>();
            	jc = JAXBContext.newInstance(new Class<?>[]{tclz},properties);
            	jaxbContextMap.put(tclz, jc);
            }else{
            	jc = jaxbContextMap.get(tclz);
            }
            
            Unmarshaller un = jc.createUnmarshaller();
            return (T) un.unmarshal(new ByteArrayInputStream(xmlstr.getBytes("utf-8")));
            
        } catch (JAXBException e) {
        	  e.printStackTrace();;
			  log.error("",e);
			 // throw new RuntimeException(e);
			  return null;
           //throw new RuntimeException(e);
        } catch (UnsupportedEncodingException e) {
        	  e.printStackTrace();;
			  log.error("",e);
			 // throw new RuntimeException(e);
			  return null;
        	  // throw new RuntimeException(e);
		}
		
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
	public static <T> T unmarshToObjBinding(Class<T> t,Class tclz [],String xmlstr) {
        try {
            JAXBContext jaxbContext  = JAXBContext.newInstance(tclz);
            Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
            return (T)unmarshaller.unmarshal(new StringReader(xmlstr));
        } catch (JAXBException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    /**
     * 将XML格式的文件转换成JAXB实现对象
     * @param <T>
     * @param tclz
     * @param file
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T unmarshToObjBinding(Class<T> tclz,File file) {
        if (tclz == null || file == null || !file.exists()) {
            return null;
        }
        
        try {
            JAXBContext jc = null;
            if(jaxbContextMap.get(tclz)==null) {
                Map<String, String> properties = new HashMap<String, String>();
                jc = JAXBContext.newInstance(new Class<?>[]{tclz},properties);
                jaxbContextMap.put(tclz, jc);
            }else{
                jc = jaxbContextMap.get(tclz);
            }
            
            Unmarshaller un = jc.createUnmarshaller();
            return (T) un.unmarshal(file);
            
        } catch (JAXBException e) {
        	  e.printStackTrace();;
			  log.error("",e);
			 // throw new RuntimeException(e);
			  return null;
        }
    }
    
    @SuppressWarnings("unchecked")
    public static <T> T unmarshToObjBinding(Class<T> tclz,InputStream inputStream) {
        if (tclz == null || inputStream == null) {
            return null;
        }
        
        try {
            JAXBContext jc = null;
            if(jaxbContextMap.get(tclz)==null) {
                Map<String, String> properties = new HashMap<String, String>();
                jc = JAXBContext.newInstance(new Class<?>[]{tclz},properties);
                jaxbContextMap.put(tclz, jc);
            }else{
                jc = jaxbContextMap.get(tclz);
            }
            
            Unmarshaller un = jc.createUnmarshaller();
            return (T) un.unmarshal(inputStream);
            
        } catch (JAXBException e) {
        	  e.printStackTrace();;
			  log.error("",e);
			 // throw new RuntimeException(e);
			  return null;
        }
    }

   
}




//public class JaxbUtil {
//
//	private static Logger log = Logger.getLogger(JaxbUtil.class);
//
//	@SuppressWarnings("unchecked")
//	public static <T> String marshToXmlBinding(Class<T> tclz, T t,
//			String encoding, boolean hasXmlDeclare) throws Exception {
//		return marshToXmlBinding(new Class[] { tclz }, t, encoding, hasXmlDeclare);
//	}
//
//	/**
//	 * 将JAXB实现对象转换成XML格式的字符串 默认UTF-8、不需要XML头
//	 * 
//	 * @param tclz
//	 * @param t
//	 * @return
//	 */
//	@SuppressWarnings("unchecked")
//	public static <T> String marshToXmlBinding(Class<T> tclz, T t) throws Exception {
//		return marshToXmlBinding(new Class[] { tclz }, t, "UTF-8", false);
//	}
//
//	/**
//	 * 将JAXB实现对象转换成XML格式的字符串
//	 * 
//	 * @param <T>
//	 *            这里的类是具体类，不能是接口
//	 * @param tclz
//	 *            转换对象实例
//	 * @param encoding
//	 *            编码
//	 * @param hasXmlDeclare
//	 *            是否生成xml声明
//	 * @return
//	 */
//	public static <T> String marshToXmlBinding(Class<Object> tclz[], T t,
//			String encoding, boolean hasXmlDeclare) throws Exception {
//		JAXBContext jc = null;
//		try {
//			Map<String, String> properties = new HashMap<String, String>();
//			// TODO 待优化，JC放入MAP形成单例模式
//			jc = JAXBContext.newInstance(tclz, properties);
//			Marshaller u = jc.createMarshaller();
//			// XML内容格式化
//			u.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
//			// 编码
//			if (StringUtils.isNotBlank(encoding)) {
//				u.setProperty(Marshaller.JAXB_ENCODING, encoding);
//			}
//			u.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
//			// 是否生成xml声明
//			if (!hasXmlDeclare) {
//				StringWriter sw = new StringWriter();
//				u.marshal(t, sw);
//				return sw.toString();
//			} else {
//				StringWriter sw = new StringWriter();
//				u.marshal(t, sw);
//				return "<?xml version=\"1.0\" encoding=\""
//						+ u.getProperty(Marshaller.JAXB_ENCODING) + "\"?>"
//						+ sw.toString();
//			}
//
//		} catch (JAXBException e) {
//			log.error(e.getMessage());
//			throw e;
//		} catch (FactoryConfigurationError e) {
//			log.error(e.getMessage());
//			throw e;
//		}
//	}
//
//	/**
//	 * 将XML格式的字符串转换成JAXB实现对象
//	 * 
//	 * @param <T>
//	 *            这里的类是具体类，不能是接口
//	 * @param tclz
//	 * @param file
//	 *            当目录存在文件不存在时，自动创建；当目录不存在时，将抛异常
//	 * @return
//	 */
//	public static <T> void marshToXmlBinding(Class<T> tclz, T t, File file) throws Exception {
//		if (tclz == null || file == null) {
//			return;
//		}
//
//		try {
//			JAXBContext jc = null;
//			Map<String, String> properties = new HashMap<String, String>();
//			jc = JAXBContext.newInstance(new Class<?>[] { tclz }, properties);
//
//			Marshaller u = jc.createMarshaller();
//			u.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
//			u.marshal(t, file);
//		} catch (JAXBException e) {
//			log.error(e.getMessage());
//			throw e;
//		}
//	}
//
//	/**
//	 * 将XML格式的字符串转换成JAXB实现对象
//	 * 
//	 * @param <T>
//	 *            这里的类是具体类，不能是接口
//	 * @param tclz
//	 * @param xmlstr
//	 * @return
//	 */
//	@SuppressWarnings("unchecked")
//	public static <T> T unmarshToObjBinding(Class<Object>[] tclz,
//			String xmlstr, String encoding) throws Exception {
//		try {
//			JAXBContext jc = null;
//			Map<String, String> properties = new HashMap<String, String>();
//			jc = JAXBContext.newInstance(tclz, properties);
//
//			Unmarshaller un = jc.createUnmarshaller();
//			if (StringUtils.isNotBlank(encoding)) {
//				return (T) un.unmarshal(new ByteArrayInputStream(xmlstr
//						.getBytes(encoding)));
//			}
//			return (T) un.unmarshal(new ByteArrayInputStream(xmlstr
//					.getBytes("utf-8")));
//
//		} catch (JAXBException e) {
//			log.error(e.getMessage());
//			throw e;
//		} catch (UnsupportedEncodingException e) {
//			log.error(e.getMessage());
//			throw e;
//		}
//
//	}
//
//	/**
//	 * 将XML格式的文件转换成JAXB实现对象
//	 * 
//	 * @param <T>
//	 * @param tclz
//	 * @param file
//	 * @return
//	 */
//	@SuppressWarnings("unchecked")
//	public static <T> T unmarshToObjBinding(Class<T> tclz, File file) throws Exception {
//		if (tclz == null || file == null || !file.exists()) {
//			return null;
//		}
//
//		try {
//			JAXBContext jc = null;
//			Map<String, String> properties = new HashMap<String, String>();
//			jc = JAXBContext.newInstance(new Class<?>[] { tclz }, properties);
//
//			Unmarshaller un = jc.createUnmarshaller();
//			return (T) un.unmarshal(file);
//
//		} catch (JAXBException e) {
//			log.error(e.getMessage());
//			throw e;
//		}
//	}
//
//	@SuppressWarnings("unchecked")
//	public static <T> T unmarshToObjBinding(Class<T> tclz,
//			InputStream inputStream) throws Exception {
//		if (tclz == null || inputStream == null) {
//			return null;
//		}
//
//		try {
//			JAXBContext jc = null;
//			Map<String, String> properties = new HashMap<String, String>();
//			jc = JAXBContext.newInstance(new Class<?>[] { tclz }, properties);
//
//			Unmarshaller un = jc.createUnmarshaller();
//			return (T) un.unmarshal(inputStream);
//
//		} catch (JAXBException e) {
//			log.error(e.getMessage());
//			throw e;
//		}
//	}
//
//}